#include "pcaphost.h"
#include "packetcapapi.h"
#include <QHostAddress>
#include <QDebug>

static CPCapAddr *analyze_addrinfo(pcap_addr *addr)
{
    CPCapAddr *pcapaddr = new CPCapAddr();
    QHostAddress haddr;
    if (addr->addr) {
        haddr.setAddress(addr->addr);
        pcapaddr->setIp(haddr.toString());
    }
    if (addr->netmask) {
        haddr.setAddress(addr->netmask);
        pcapaddr->setNetmask(haddr.toString());
    }
    if (addr->broadaddr) {
        haddr.setAddress(addr->broadaddr);
        pcapaddr->setBroadcast(haddr.toString());
    }
    if (addr->dstaddr) {
        haddr.setAddress(addr->dstaddr);
        pcapaddr->setDstaddr(haddr.toString());
    }
    return pcapaddr;
}

static CPCapDev *analyze_devinfo(pcap_if_t *dev)
{
    CPCapDev *pcapdev = new CPCapDev();
    pcapdev->setSource(dev->name);
    pcapdev->setDescription(dev->description);
    for (pcap_addr *addr = dev->addresses; addr != NULL; addr = addr->next) {
        pcapdev->apendAddr(analyze_addrinfo(addr));
    }
    return pcapdev;
}

CPCapHost::CPCapHost(QObject *parent) : QObject(parent)
{
    qDebug("[CPCapHost]constructed");
}

CPCapHost::~CPCapHost()
{
    qDebug("[CPCapHost]destroyed");
    clear_devs();
}

CPCapAuth *CPCapHost::author() const
{
    return m_author;
}

void CPCapHost::setAuthor(CPCapAuth *author)
{
    m_author = author;
    emit authorChanged();
}

QQmlListProperty<CPCapDev> CPCapHost::devs()
{
    return QQmlListProperty<CPCapDev>(this, m_devs);
}

void CPCapHost::clearDevs()
{
    clear_devs();
    emit devsUpdated();
}

void CPCapHost::updateDevs()
{
    clear_devs();

    pcap_if_t *alldevs = NULL;
    char errbuf[PCAP_ERRBUF_SIZE];
    int result = wpcap_api_arg4(pcap_findalldevs_ex, PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf);
    if (result == -1) {
        qCritical() << errbuf;
    } else {
        for (pcap_if_t *dev = alldevs; dev != NULL; dev = dev->next) {
            m_devs.append(analyze_devinfo(dev));
        }
        wpcap_api_arg1(pcap_freealldevs, alldevs);
    }
    emit devsUpdated();
}

CPCapDev *CPCapHost::findDev(int inx)
{
    Q_UNUSED(inx);
    return Q_NULLPTR;
}

CPCapDev *CPCapHost::findDev(const QString &name)
{
    Q_UNUSED(name);
    return Q_NULLPTR;
}

void CPCapHost::clear_devs()
{
    foreach (CPCapDev *dev, m_devs) {
        delete dev;
    }
    m_devs.clear();
}
